﻿using DDBS_Server.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DDBS_Klient
{
    public partial class Form1 : Form
    {
        //private string server_url = "http://localhost/DDBS_Server/";
        private string server_url = "http://localhost:19692/DDBS_Server/";
       
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            LoadShardList();
            LogLine("Ready.");
        }

        private void LoadShardList()
        {
            List<String> shardNames = new List<String>();

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(server_url);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                try
                {
                    HttpResponseMessage response = client.GetAsync("api/samples/shardlist").GetAwaiter().GetResult();
                    response.EnsureSuccessStatusCode(); // Throw exception if not a success code.

                    string r = (";") + response.Content.ReadAsAsync<string>().Result;
                    shardNames = r.Split(';').ToList();
                }
                catch (HttpRequestException exception)
                {
                    Log(exception.ToString());
                }
            }

            comboBox_shardList.DataSource = shardNames;
            comboBox_shardList2.DataSource = shardNames;
        }

        private void Log(string text)
        {
            log.AppendText(text);
        }

        private void LogLine(string text)
        {
            Log(text+"\r\n");
        }

        private async void button_test(object sender, EventArgs e)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(server_url);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                try
                {
                    HttpResponseMessage response = await client.GetAsync("api/samples");
                    response.EnsureSuccessStatusCode(); // Throw exception if not a success code.

                    Log(response.Content.ReadAsAsync<string>().Result);
                }
                catch (HttpRequestException exception)
                {
                    Log(exception.ToString());
                }
            }
        }

        private void button_getSamplePTB_Click(object sender, EventArgs e)
        {
            SamplesRequest sr = new SamplesRequest();
            string data;
            if (texbox_simSamplePath.Text == "") return;
            try
            {
                Sample simSample = new Sample("simSample");
                data = File.ReadAllText(texbox_simSamplePath.Text);
                simSample.PeaksFromCSV(data);
                sr.simSample = simSample;
                sr.tolerance = float.Parse(textBox_tolerance.Text);
                sr.ratioTolerance = float.Parse(textBox_rtolerance.Text);
            }
            catch (IOException)
            {
                LogLine("Cannot parse simSample.");
                return;
            }

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(server_url);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                try
                {
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    List<Sample> results = null;
                    var task = client.PostAsJsonAsync("api/samples/getsamplesbtp", sr)
                      .ContinueWith((taskwithresponse) =>
                      {
                          var response = taskwithresponse.Result;
                          var jsonString = response.Content.ReadAsStringAsync();
                          jsonString.Wait();
                          results = JsonConvert.DeserializeObject<List<Sample>>(jsonString.Result);
                      });
                    task.Wait();
                    watch.Stop();
                    LogLine("Count: " + results.Count);
                    LogLine("Time: " + watch.ElapsedMilliseconds.ToString());
                    foreach (Sample s in results) LogLine(s.ToString());
                }
                catch (HttpRequestException exception)
                {
                    Log(exception.ToString());
                }
            }
        }

        private void button_LoadFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFD = new OpenFileDialog();
            DialogResult result = openFD.ShowDialog(); // Show the dialog.
            if (result == DialogResult.OK) texbox_simSamplePath.Text = openFD.FileName;
            else return;
        }

        private async void button_storeRandSamples_Click(object sender, EventArgs e)
        {
            List<Sample> randSamples = generateSamples();

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(server_url);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                try
                {
                    HttpResponseMessage response = await client.PostAsJsonAsync("api/samples/storeRandSamples", randSamples);
                    response.EnsureSuccessStatusCode(); // Throw exception if not a success code.
                    LogLine(response.Content.ReadAsAsync<string>().Result);
                }
                catch (HttpRequestException exception)
                {
                    LogLine(exception.ToString());
                }
            }
        }

        private List<Sample> generateSamples()
        {
            Random rand = new Random();
            List<Sample> list = new List<Sample>();
            List<Sample> shuffList = new List<Sample>();
            int countR, countS;
            string shard = textBox_shard.Text;
            try
            {
                countR = Int16.Parse(textBox_randSamplesCountR.Text);
                countS = Int16.Parse(textBox_randSamplesCountS.Text);
            }
            catch 
            {
                LogLine("Cannot parse values.");
                return shuffList; 
            }

            // get list of random samples (each with some similar samples)
            for (int r = 0; r < countR; r++)
            {

                // generate samples name
                var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                string name = "Sample_";
                name += new string(
                            Enumerable.Repeat(chars, 8)
                            .Select(s => s[rand.Next(s.Length)])
                            .ToArray());
                
                // random sample
                List<Peak> peaks = new List<Peak>();
                float max = 100;
                while (max > 0)
                {
                    double M = rand.NextDouble() * 100;
                    peaks.Add(new Peak(M, max));
                    max -= (float)(rand.NextDouble() * 15);
                }
                Sample randSample = new Sample(name, shard, peaks.OrderBy(p => p.M).ToList());
                list.Add(randSample);

                // similar samples
                for (int s = 0; s < countS - 1; s++)
                {
                    List<Peak> simPeaks = new List<Peak>();
                    foreach (Peak p in randSample.Peaks)
                    {
                        double newM = p.M + (rand.NextDouble() * 2);
                        float newV;
                        if (p.V == 100) newV = p.V;
                        else newV = p.V - (float)(rand.NextDouble() * 5);
                        if (newV < 0) newV = 0;
                        simPeaks.Add(new Peak(newM, newV));
                    }
                    Sample simSample = new Sample(name, shard, simPeaks.OrderBy(p => p.M).ToList());
                    list.Add(simSample);
                }
            }

            // store samples in random order
            while (list.Count > 0)
            {
                int i = rand.Next(list.Count);
                shuffList.Add(list[i]);
                list.RemoveAt(i);
            }

            return shuffList;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.textBox_shard.Text = comboBox_shardList.SelectedValue.ToString();
        }

        private void comboBox_shardList2_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.textBox_shard2.Text = comboBox_shardList2.SelectedValue.ToString();
        }

        private void button_selectFileSample_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "Text files|*.txt;*.csv|All files (*.*)|*.*"; // file types, that will be allowed to upload
            dialog.Multiselect = false; // allow/deny user to upload more than one file at a time
            if (dialog.ShowDialog() == DialogResult.OK) 
            {
                textBox_samplePath.Text = dialog.FileName;
            }
        }

        private async void button_storeSample_Click(object sender, EventArgs e)
        {
            string filepath = textBox_samplePath.Text;
            string filename = Path.GetFileNameWithoutExtension(filepath);

            using (var client = new HttpClient())
                using (var content = new MultipartFormDataContent())
                {
                    client.BaseAddress = new Uri(server_url);

                    try
                    {
                        var fileContent = new ByteArrayContent(File.ReadAllBytes(filepath));
                        fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment"){FileName = filename};
                        content.Add(fileContent);
                        content.Add(new StringContent(textBox_shard2.Text), "shard");
                        HttpResponseMessage response = await client.PostAsync("api/samples/storeSamples", content);
                        LogLine(response.StatusCode.ToString());
                    }
                    catch (HttpRequestException exception)
                    {
                        LogLine(exception.ToString());
                    }
                }
        }

        private void textbox_server_TextChanged(object sender, EventArgs e)
        {
            server_url = textbox_server.Text;
        }

    }
}
